/*
 * Copyright 2005-2013 rsico. All rights reserved.
 * Support: http://www.rsico.cn
 * License: http://www.rsico.cn/license
 */
package com.rzico.account.plugin.alipay;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.rzico.account.entity.Payment;
import com.rzico.account.entity.Refunds;
import com.rzico.account.service.PaymentService;
import com.rzico.account.service.RefundsService;
import com.rzico.core.entity.SysPlugin;
import com.rzico.core.entity.SysUser;
import com.rzico.core.model.PluginAttribute;
import com.rzico.core.plugin.PaymentPlugin;
import com.rzico.util.MD5Utils;
import com.rzico.util.XMLUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

/**
 * Plugin - 支付宝(普通商户/特约商户)
 * @author rsico Team
 * @version 3.0
 */
@Component("alipayAppPlugin")
@Slf4j
public class AlipayAppPlugin extends PaymentPlugin {

	public static final String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
	public static final String REFUNDS_ORDER_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";

	@Value("${weixin.appid}")
	private String wx_appid;
	@Value("${weixin.mchid}")
	private String wx_mchid;
	@Value("${weixin.mchSecret}")
	private String wx_mch_secret;
	@Value("${setting.host}")
	private String host;

	@Autowired
	@Lazy
	private PaymentService paymentService;

	@Autowired
	@Lazy
	private RefundsService refundsService;

	@Override
	public String getName() {
		return "支付宝(APP)";
	}

	@Override
	public String getVersion() {
		return "1.0";
	}

	@Override
	public List<PluginAttribute> getAttributeKeys() {
		List<PluginAttribute> data = new ArrayList<>();
		data.add(new PluginAttribute("appid","appid",PluginAttribute.STRING_VALUE));
		data.add(new PluginAttribute("APP_PRIVATE_KEY","商户私钥",PluginAttribute.STRING_VALUE,null,false));
		data.add(new PluginAttribute("ALIPAY_PUBLIC_KEY","支付宝公钥",PluginAttribute.STRING_VALUE,null,false));
		return data;
	}

	@Override
	public Map<String, Object> trade(SysPlugin sysPlugin,String tradeNo, String description, BigDecimal totalfee, String userId, HttpServletRequest request) {

		//实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(
				"https://openapi.alipay.com/gateway.do",
				sysPlugin.getAttribute("appid"),
				sysPlugin.getAttribute("APP_PRIVATE_KEY"),
				  "json",
				 "UTF-8",
				sysPlugin.getAttribute("ALIPAY_PUBLIC_KEY"),
				"RSA2"
		);

        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
		AlipayTradeAppPayRequest req = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
		AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();

		if (description.length()>40) {
			model.setBody(description.substring(0, 40));
		} else {
			model.setBody(description);
		}
		model.setOutTradeNo(tradeNo);
		model.setTimeoutExpress("30m");
		model.setSubject(model.getBody());
		model.setTotalAmount(totalfee.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
		model.setProductCode("QUICK_MSECURITY_PAY");
		req.setBizModel(model);
		req.setNotifyUrl(getNotifyUrl(sysPlugin));
		HashMap<String, Object> finalpackage = new HashMap<>();

		try {

			//这里和普通的接口调用不同，使用的是sdkExecute
			AlipayTradeAppPayResponse response = alipayClient.sdkExecute(req);

			//System.out.println(response.getBody());//就是orderString 可以直接给客户端请求，无需再做处理。

			if(response.isSuccess()){
				finalpackage.put("tranSn", response.getTradeNo());
				finalpackage.put("return_code", "0000");
				finalpackage.put("payData",response.getBody());
			} else {
				finalpackage.put("return_code", "0003");
				finalpackage.put("error_msg",response.getSubMsg());
			}

		} catch (AlipayApiException e) {
			finalpackage.put("return_code", "0003");
			finalpackage.put("error_msg","发起支付失败");
		}

        return finalpackage;


	}

	@Override
	public Map<String, Object> verifyNotify(SysPlugin sysPlugin,HttpServletRequest request) {

		//获取支付宝POST过来反馈信息
		Map<String,String> params = new HashMap<String,String>();
		Map requestParams = request.getParameterMap();
		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			//乱码解决，这段代码在出现乱码时使用。
			//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			params.put(name, valueStr);
		}


		HashMap<String, Object> finalpackage = new HashMap<>();
		try {
			//切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
			//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
			boolean flag = AlipaySignature.rsaCheckV1(params, sysPlugin.getAttribute("ALIPAY_PUBLIC_KEY"), "UTF-8","RSA2");

			if (flag && ("TRADE_SUCCESS".equals(params.get("trade_status")) || "TRADE_FINISHED".equals(params.get("trade_status")))
			   ) {
					finalpackage.put("return_code", "0000");
					finalpackage.put("tradeNo", (String) params.get("out_trade_no"));
					finalpackage.put("tranSn", (String) params.get("trade_no"));
					return finalpackage;
			}
			finalpackage.put("return_code", "9999");
			finalpackage.put("error_msg",params.get("return_msg"));

		} catch (Exception e) {
			finalpackage.put("return_code", "9999");
			finalpackage.put("error_msg", e.getMessage());
		}

		return finalpackage;
	}

	/**
	 * 查询订单的支付结果  0000成功  9999处理中  其他的失败
	 */
	@Override
	public Map<String, Object> tradeQuery(SysPlugin sysPlugin,String tradeNo,String tranSn,HttpServletRequest request) {

        //实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(
				"https://openapi.alipay.com/gateway.do",
				sysPlugin.getAttribute("appid"),
				sysPlugin.getAttribute("APP_PRIVATE_KEY"),
				"json",
				"UTF-8",
				sysPlugin.getAttribute("ALIPAY_PUBLIC_KEY"),
				"RSA2"
		);

		AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();
		queryRequest.setBizContent("{" +
				"\"out_trade_no\":\""+tradeNo+"\"}");
		HashMap<String, Object> finalpackage = new HashMap<>();
		try {
			AlipayTradeQueryResponse response = alipayClient.execute(queryRequest);
			if(response.isSuccess()){

				String status = response.getTradeStatus();
				if (status.equals("TRADE_SUCCESS")) {
					finalpackage.put("tranSn", response.getTradeNo());
					finalpackage.put("return_code", "0000");
					finalpackage.put("error_msg","支付成功");
				} else
				if (status.equals("TRADE_FINISHED")) {
					finalpackage.put("tranSn", response.getTradeNo());
					finalpackage.put("return_code", "0000");
					finalpackage.put("error_msg","支付成功");
				} else if (status.equals("WAIT_BUYER_PAY")) {
					finalpackage.put("return_code", "0001");
					finalpackage.put("error_msg","正在付款");
				} else if (status.equals("TRADE_CLOSED")) {
					finalpackage.put("return_code", "0001");
					finalpackage.put("error_msg","交易关闭");
				} else {
					finalpackage.put("return_code", "0003");
					finalpackage.put("error_msg", response.getSubMsg());
				}


			} else {
				finalpackage.put("return_code", "0003");
				finalpackage.put("error_msg",response.getSubMsg());
			}

		} catch (Exception e) {
			finalpackage.put("return_code", "9999");
			finalpackage.put("error_msg", e.getMessage());
		}

		return finalpackage;
	}

	@Override
	public String getNotifyMessage(HttpServletRequest request) {
		return "SUCCESS";
	}

	/**
	 * 申请退款
	 */
	@Override
	public Map<String, Object> refund(SysPlugin sysPlugin, String refundNo, String tradeNo, BigDecimal totalfee, BigDecimal refundfee , HttpServletRequest request) {

		//实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(
				"https://openapi.alipay.com/gateway.do",
				sysPlugin.getAttribute("appid"),
				sysPlugin.getAttribute("APP_PRIVATE_KEY"),
				"json",
				"UTF-8",
				sysPlugin.getAttribute("ALIPAY_PUBLIC_KEY"),
				"RSA2"
		);
		AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();

		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		DecimalFormat decimalFormat = new DecimalFormat("#0.00");
		paramsMap.put("out_trade_no",tradeNo);
		paramsMap.put("out_request_no",refundNo);
		paramsMap.put("refund_amount", decimalFormat.format(refundfee.setScale(2,BigDecimal.ROUND_HALF_DOWN)));

		HashMap<String, Object> finalpackage = new HashMap<String, Object>();
		refundRequest.setBizContent(JSON.toJSONString(paramsMap));

		try {

			AlipayTradeRefundResponse response = alipayClient.execute(refundRequest);
			if(response.isSuccess()){
				finalpackage.put("tranSn", response.getTradeNo());
				finalpackage.put("return_code", "0000");
			} else {
				finalpackage.put("return_code", "0003");
				finalpackage.put("error_msg",response.getSubMsg());
			}


		} catch (Exception e) {
			finalpackage.put("return_code", "0003");
			finalpackage.put("error_msg", e.getMessage());
		}
		return finalpackage;


	}

	/**
	 * 查询退款
	 */
	@Override
	public Map<String, Object> refundQuery(SysPlugin sysPlugin, String refundNo,String tranSn, HttpServletRequest request) {


		//实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(
				"https://openapi.alipay.com/gateway.do",
				sysPlugin.getAttribute("appid"),
				sysPlugin.getAttribute("APP_PRIVATE_KEY"),
				"json",
				"UTF-8",
				sysPlugin.getAttribute("ALIPAY_PUBLIC_KEY"),
				"RSA2"
		);

		Refunds refunds = refundsService.findBySn(refundNo);

		Payment payment = paymentService.selectByPrimaryKey(refunds.getPaymentId());

		AlipayTradeFastpayRefundQueryRequest queryRequest = new AlipayTradeFastpayRefundQueryRequest();

		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("out_trade_no",payment.getSn());
		paramsMap.put("out_request_no",refundNo);

		HashMap<String, Object> finalpackage = new HashMap<String, Object>();

		try {

			queryRequest.setBizContent(JSON.toJSONString(paramsMap));
			AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(queryRequest);
			if(response.isSuccess()){
				if ("REFUND_SUCCESS".equals(response.getRefundStatus()) || response.getRefundStatus()==null) {
					finalpackage.put("tranSn", response.getTradeNo());
					finalpackage.put("return_code", "0000");
				} else {
					finalpackage.put("return_code", "0003");
					finalpackage.put("error_msg",response.getSubMsg());
				}
			} else {
				finalpackage.put("return_code", "0003");
				finalpackage.put("error_msg",response.getSubMsg());
			}


		} catch (Exception e) {
			finalpackage.put("return_code", "9999");
			finalpackage.put("error_msg", e.getMessage());
		}
		return finalpackage;

	}

}